src/pages/posts/[...page].astro 2.9 K raw
1
---
2
import type { Page, GetStaticPathsOptions } from "astro";
3
import type { CollectionEntry } from "astro:content";
4
import { getCollection } from "astro:content";
5
import PageLayout from "@/layouts/Base.astro";
6
import PostPreview from "@/components/blog/PostPreview.astro";
7
import Pagination from "@/components/common/Paginator.astro";
8
import { getUniqueTags, sortMDByDate } from "@/utils";
9
10
export async function getStaticPaths({ paginate }: GetStaticPathsOptions) {
11
	const allPosts = await getCollection("post");
12
	const visiblePosts = allPosts.filter((post) => !post.data.hidden);
13
	const allPostsByDate = sortMDByDate(visiblePosts);
14
	const uniqueTags = getUniqueTags(allPosts);
15
	return paginate(allPostsByDate, { props: { uniqueTags }, pageSize: 10 });
16
}
17
18
interface Props {
19
	page: Page<CollectionEntry<"post">>;
20
	uniqueTags: string[];
21
}
22
23
const { page, uniqueTags } = Astro.props;
24
25
const meta = {
26
	title: "/blog",
27
	description: "Posts by Steve",
28
};
29
30
const paginationProps = {
31
	...(page.url.prev && {
32
		prevUrl: {
33
			url: page.url.prev,
34
			text: "← Previous Posts",
35
		},
36
	}),
37
	...(page.url.next && {
38
		nextUrl: {
39
			url: page.url.next,
40
			text: "Next Posts →",
41
		},
42
	}),
43
};
44
---
45
46
<PageLayout meta={meta}>
47
  <h1 class="title mb-6">/blog</h1>
48
	<div class="grid gap-y-16 sm:grid-cols-[3fr_1fr] sm:gap-x-8">
49
		<section aria-label="Blog post list">
50
			<ul class="space-y-8 text-left">
51
				{
52
					page.data.map((p) => (
53
						<li class="flex flex-col flex-wrap gap-x-2 sm:flex-row [&_q]:w-full">
54
							<PostPreview post={p} as="h2" withDesc />
55
						</li>
56
					))
57
				}
58
			</ul>
59
			<Pagination {...paginationProps} />
60
		</section>
61
		{
62
			uniqueTags.length && (
63
				<aside>
64
					<h2 class="mb-4 flex items-center text-lg font-semibold">
65
						<svg
66
							aria-hidden="true"
67
							xmlns="http://www.w3.org/2000/svg"
68
							class="h-6 w-6"
69
							viewBox="0 0 24 24"
70
							stroke-width="1.5"
71
							stroke="currentColor"
72
							fill="none"
73
							stroke-linecap="round"
74
							stroke-linejoin="round"
75
						>
76
							<path stroke="none" d="M0 0h24v24H0z" fill="none" />
77
							<path d="M7.859 6h-2.834a2.025 2.025 0 0 0 -2.025 2.025v2.834c0 .537 .213 1.052 .593 1.432l6.116 6.116a2.025 2.025 0 0 0 2.864 0l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-6.117 -6.116a2.025 2.025 0 0 0 -1.431 -.593z" />
78
							<path d="M17.573 18.407l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-7.117 -7.116" />
79
							<path d="M6 9h-.01" />
80
						</svg>
81
						Tags
82
					</h2>
83
					<ul class="flex flex-wrap gap-2 text-bgColor">
84
						{uniqueTags.map((tag) => (
85
							<li>
86
								<a
87
									class="flex items-center justify-center rounded-lg bg-accent p-1"
88
									href={`/tags/${tag}`}
89
									aria-label={`View all posts with the tag: ${tag}`}
90
								>
91
									{tag}
92
								</a>
93
							</li>
94
						))}
95
					</ul>
96
					<span class="mt-4 block sm:text-right">
97
						<a class="sm:hover:text-accent" href="/tags" aria-label="View all blog categories">
98
							View all →
99
						</a>
100
					</span>
101
				</aside>
102
			)
103
		}
104
	</div>
105
</PageLayout>